// vim: foldmethod=marker : foldmarker=<<<,>>>
/*
 File: page.c
 Generated-From: page.nw
*/
#include "hooverPch.h"

#include "branch/branch.h"
#include "hoover/rod.h"
#include "nis/page.h"
#include "nis/page.rh"
#include "nis/payload.h"
PWSTR className__nis_page=L"nis_page";
hidden_q i_t createMenubar(nis_page_p this) {
  i_t rs; SHMENUBARINFO mbi;

  mzero(&mbi,sizeof(SHMENUBARINFO));
  mbi.cbSize=sizeof(SHMENUBARINFO);
  mbi.hwndParent=this->window; mbi.dwFlags=SHCMBF_HMENU;
  mbi.hInstRes=this->rod->instance;
  mbi.nToolBarId=MENU__nis_page;

  rs=SHCreateMenuBar(&mbi);
  this->menubar=mbi.hwndMB;
 
// mzero(&this->SAI,sizeof(SHACTIVATEINFO));
// this->SAI.cbSize=sizeof(SHACTIVATEINFO);
  return rs;
};

hidden_q i_t createStatus(nis_page_p this) {
  this->status=CreateWindowEx(0,STATUSCLASSNAME,0,WS_VISIBLE|WS_CHILD,
   0,0,0,0,
   this->window,(HANDLE)3,this->rod->instance,NULL);
  return this->status!=NULL;
};

#define DETAIL_HEIGHT 68
hidden_q i_t createDetail(nis_page_p this) {
  RECT rc; i_t ht;
 
  GetWindowRect(this->status,&rc);
  ht=rc.bottom-rc.top;

  GetClientRect(this->window,&rc);

  this->detail=CreateWindowEx(0,L"EDIT",0,
    WS_VISIBLE|WS_BORDER|WS_CHILD|ES_MULTILINE|ES_WANTRETURN|
    ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_READONLY|WS_VSCROLL,
    -1,rc.bottom-ht-DETAIL_HEIGHT,
    rc.right+2,DETAIL_HEIGHT,
    this->window,(HANDLE)2,this->rod->instance,NULL);

  return this->detail!=NULL;
};

hidden_q i_t createList(nis_page_p this) {
  v_p ls; LVCOLUMN col; RECT rc; i_t ht;
 
  GetWindowRect(this->status,&rc);
  ht=rc.bottom-rc.top; ht+=DETAIL_HEIGHT;
 
  GetClientRect(this->window,&rc);
  ls=CreateWindowEx(0,WC_LISTVIEW,0,
    WS_BORDER|WS_VISIBLE|WS_CHILD|LVS_REPORT|LVS_NOSORTHEADER|LVS_SINGLESEL,
    -1,-1,rc.right+2,rc.bottom-ht+2,
    this->window,(HMENU)1,this->rod->instance,NULL);
  if (ls==NULL) return 0;

  ListView_SetExtendedListViewStyle(ls,LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES);
  //|LVS_EX_GRADIENT|LVS_EX_GRIDLINES
 
  col.mask=LVCF_SUBITEM|LVCF_TEXT|LVCF_WIDTH|LVCF_FMT;
  col.iSubItem=1; col.pszText=L"Program";
  col.cx=180; col.fmt=LVCFMT_LEFT;
  ListView_InsertColumn(ls,0,&col);

  this->infos=ls;
  return 1;
};

hidden_q v_t checkSortBy(nis_page_p this, i_t sortBy);

nis_page_p create__nis_page(HWND h, LPCREATESTRUCT cs) {
  WARP(hoover_rod_p,rod,cs->lpCreateParams);
  nis_page_p this=claim__heap_steward(rod->heap,sizeof(nis_page_t));
  SIGNAL(null(this),none,fail0);
  this->window=h; this->rod=rod;
  SetWindowLong(h,GWL_USERDATA,(LONG)this);
 
  SIGNAL(unless(createMenubar(this)),none,fail1);
  checkSortBy(this,SORT_BY_NONE__nis_page);
  
  //in case of error child windows are destroyed by owner DestroyWindow
  SIGNAL(if(!(createStatus(this) && createDetail(this) && createList(this))),
    none,fail1);
  return this;
fail2: DestroyWindow(this->menubar);
fail1: retract__heap_steward(this->rod->heap,this,sizeof(nis_page_t));
fail0: return NULL;
};

v_t demolish__nis_page(nis_page_p this) {
 DestroyWindow(this->menubar);
 retract__heap_steward(this->rod->heap,this,sizeof(nis_page_t));
 };
hidden_q LRESULT CALLBACK wndproc(HWND h, UINT m, WPARAM w, LPARAM l);

i_t register__nis_page(hoover_rod_p rod) {
 WNDCLASS wc;
 mzero(&wc,sizeof(WNDCLASS));
 wc.style=CS_HREDRAW|CS_VREDRAW;
 wc.lpfnWndProc=(WNDPROC)wndproc;
 wc.hInstance=rod->instance;
 wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 wc.lpszClassName=className__nis_page;
 return RegisterClass(&wc);
 };
hidden_q v_t checkSortBy(nis_page_p this, i_t sortBy) {
  i_t pos;
  HMENU h=(HMENU)SendMessage(this->menubar,SHCMBM_GETMENU,0,0);
  h=GetSubMenu(h,1);
  h=GetSubMenu(h,3);
  
  switch (sortBy) {
  case SORT_BY_NAME__nis_page: pos=1; break;
  case SORT_BY_DATE__nis_page: pos=2; break;
  default: pos=0;
  };
  
  CheckMenuRadioItem(h,0,2,pos,MF_BYPOSITION);
  this->order.sortBy=sortBy;
};

hidden_q v_t updateStatus(nis_page_p this) {
  WCHAR buf[64];
  i_t i,checked;
  for (i=0,checked=0;i<this->rod->payload.qnt;i++) {
    if (ListView_GetCheckState(this->infos,i)) checked++;
  };
  _snwprintf(buf,64,L"total: %d checked: %d",this->rod->payload.qnt,checked);
  SendMessage(this->status,SB_SETTEXT,0|SBT_NOBORDERS,(LPARAM)buf);
};

v_t fillList(nis_page_p this) {
  int i;

  ListView_DeleteAllItems(this->infos);
  ListView_SetItemCount(this->infos,this->rod->payload.qnt);
  
  switch (this->order.sortBy) {
  case SORT_BY_NAME__nis_page: 
    this->order.entries=this->rod->payload.sortBy.name;
    break;
  case SORT_BY_DATE__nis_page: 
    this->order.entries=this->rod->payload.sortBy.date;
    break;
  default: this->order.entries=this->rod->payload.sortBy.none;
  };

  for (i=0;i<this->rod->payload.qnt;i++) {
    nis_entry_p e=this->order.entries[i];
    LVITEM lvi;
    lvi.mask=LVIF_TEXT|LVIF_PARAM;
    lvi.pszText=e->application;
    lvi.iItem=i; lvi.iSubItem=0;
    lvi.lParam=e-this->rod->payload.entries;
    ListView_InsertItem(this->infos,&lvi);
  };
};

v_t onUpdateNis(nis_page_p this) {
  update__nis_payload(&this->rod->payload);
  fillList(this);
  updateStatus(this);
}
 

v_t onRemoveNi(nis_page_p this) {
  i_t rs,i,index;
  rs=MessageBox(this->window,L"Are you sure to remove checked items?",
    L"Confirmation",MB_YESNO|MB_ICONQUESTION|MB_SETFOREGROUND|MB_DEFBUTTON2);
  if (rs!=IDYES) return;
 
  for (i=0;i<this->rod->payload.qnt;i++) {
    BOOL isChecked=ListView_GetCheckState(this->infos,i);
    if (isChecked) {
      index=this->order.entries[i]-this->rod->payload.entries;
      remove__nis_payload(&this->rod->payload,index);
    };
  };
  onUpdateNis(this);
};

v_t onClearChecks(nis_page_p this) {
  i_t i;
  for (i=0;i<this->rod->payload.qnt;i++)
    ListView_SetItemState(this->infos,i,
      INDEXTOSTATEIMAGEMASK(1),LVIS_STATEIMAGEMASK);
  updateStatus(this);
};

v_t onCheckDups(nis_page_p this) {
  i_t i,j;
  onClearChecks(this);
  for (i=0;i<this->rod->payload.qnt;i++) {
    nis_entry_p e=this->order.entries[i];

    for (j=i+1;j<this->rod->payload.qnt;j++) {
      nis_entry_p assay=this->order.entries[j];

      BOOL isChecked=ListView_GetCheckState(this->infos,j);
      if (!isChecked && isDuplicate__nis_entry(e,assay))
        ListView_SetItemState(this->infos,j,
          INDEXTOSTATEIMAGEMASK(2),LVIS_STATEIMAGEMASK);
    };
  };
  updateStatus(this);
};

v_t onSortBy(nis_page_p this, i_t sortBy) {
  checkSortBy(this,sortBy);
  fillList(this);
  updateStatus(this);
};

LRESULT onCommand(nis_page_p this, HWND ctl, WORD id, WORD code) {
  LRESULT rs=0;
  switch(id) {
  case EXIT__nis_page: PostMessage(0,DEMOLISH__hoover_rod,0,0); break;
  case UPDATE__nis_page: onUpdateNis(this); break;
  case REMOVE_CHECKED__nis_page: onRemoveNi(this); break;
  case CHECK_DUPLICATION__nis_page: onCheckDups(this); break;
  case CLEAR_CHECKS__nis_page: onClearChecks(this); break;
  case SORT_BY_NONE__nis_page:
  case SORT_BY_NAME__nis_page:
  case SORT_BY_DATE__nis_page: onSortBy(this,id); break;
  };
  return rs;
};

v_t onItemActivate(nis_page_p this, NMLISTVIEW * header) {
  if (header->iItem<0 || header->iItem>=this->rod->payload.qnt) return;
  ListView_SetItemState(this->infos,header->iItem,
    INDEXTOSTATEIMAGEMASK(
      ListView_GetCheckState(this->infos,header->iItem)?1:2),
    LVIS_STATEIMAGEMASK);
};

v_t onItemChanged(nis_page_p this, NMLISTVIEW * header) {
  nis_entry_p e; is_t index;
  updateStatus(this);
  if (!((header->uChanged&LVIF_STATE) && (header->uNewState&LVIS_FOCUSED)))
    return;
 
  SetWindowText(this->detail,L"");
  index=header->lParam;
  if (index<0 || index>=this->rod->payload.qnt) return;
 
  e=this->rod->payload.entries+index;
  spell__nis_entry(e,this->detail);
};

LRESULT onNotify(nis_page_p this, NMHDR * header) {
  LRESULT rs=0;
  switch(header->code) {
  case LVN_ITEMACTIVATE: onItemActivate(this,(NMLISTVIEW *)header); break;
  case LVN_ITEMCHANGED: onItemChanged(this,(NMLISTVIEW *)header); break;
  };
  return rs;
};

hidden_q LRESULT CALLBACK wndproc(HWND h, UINT m, WPARAM w, LPARAM l) {
  LRESULT rs=0;
  WARP(nis_page_p,this,GetWindowLong(h,GWL_USERDATA));
  switch(m) {
  case WM_CREATE: 
    rs=create__nis_page(h,(LPCREATESTRUCT)l)?0:-1; 
    break;
  case WM_DESTROY:
    if (this!=NULL) demolish__nis_page(this);
    break;
  case WM_CLOSE: PostMessage(0,DEMOLISH__hoover_rod,0,0); break;
 // case WM_LBUTTONUP: PostMessage(0,TM_REALM_DEMOLISH,0,0); break;
  case WM_COMMAND: rs=onCommand(this,(HWND)l,LOWORD(w),HIWORD(w)); break;
 //  case WM_ACTIVATE: wiBedActivate(h,w,l); break;
 //  case WM_SIZE: wiBedSize(h,LOWORD(l),HIWORD(l)); break;
  case WM_NOTIFY: rs=onNotify(this,(NMHDR *)l); break;
  default: rs=DefWindowProc(h,m,w,l); break;
  };
  return rs;
};      
